#include "music.h"
#include "ui_music.h"

Music::Music(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Music)
{
    ui->setupUi(this);
    //初始化工作是在创建了UI之后
    initUI();
    initPlayer();
    connectSignalAndSlot();
}

Music::~Music()
{
    delete ui;
}

void Music::initUI()
{
    //设置无标题栏
    this->setWindowFlag(Qt::WindowType::FramelessWindowHint);
    //设置边框透明
    this->setAttribute(Qt::WA_TranslucentBackground);
    //设置任务栏图标
    setWindowIcon(QIcon(":/images/tubiao.png"));
    ui->max->setEnabled(false);         //禁用最大化，暂时不支持
    //设置模糊边框
    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setOffset(0,0);           //设置阴影偏移
    shadowEffect->setColor("#000000");      //设置颜色为黑色
    shadowEffect->setBlurRadius(10);        //设置阴影的模糊半径
    this->setGraphicsEffect(shadowEffect);

    //初始化body中的6个控件btForm信息
    ui->Rec->setIcon(":/images/rec.png","推荐",1);
    ui->music->setIcon(":/images/music.png","音乐馆",2);
    ui->audio->setIcon(":/images/radio.png","电台",3);
    ui->like->setIcon(":/images/like.png","我喜欢",4);
    ui->local->setIcon(":/images/local.png","本地下载",5);
    ui->recent->setIcon(":/images/recent.png","最近播放",6);

    //初始化的时候只有在local的界面是展示动画效果的其他的界面并不展示
    ui->local->showAnimal();
    //右边的界面默认打开的是我喜欢的界面
    ui->stackedWidget->setCurrentIndex(4);
    curPage = ui->localPage;        //默认播放的是本地的音乐

    //设置推荐界面的ui         --todo:保证推荐的音乐和补给的音乐不同
    srand(time(nullptr));
    QJsonArray data = randomPicture();
    ui->recMusicBox->initRecBoxUI(data,1);
    ui->supplyMusicBox->initRecBoxUI(data,2);

    //初始化我喜欢，本地音乐，最近播放3个界面
    ui->likePage->setCommonPageUI("我喜欢",":/images/ilikebg.png");
    ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->localPage->setCommonPageUI("本地音乐",":/images/localbg.png");
    ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->recentPage->setCommonPageUI("最近播放",":/images/recentbg.png");
    ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);

    //初始化播放控制区图标
    ui->Play->setIcon(QIcon(":/images/play_2.png"));            //默认为暂停图标
    ui->playMode->setIcon(QIcon(":/images/shuffle_2.png"));     //默认为随机播放
    //初始化音量按钮
    volumeTool = new VolumeTool(this);
    //初始化lrc词界面
    lrcPage = new LrcPage(this);
    lrcPage->setGeometry(10,10,lrcPage->width(),lrcPage->height());
    lrcPage->hide();
    //给lrc界面打开的时候添加对应的动画效果
    lrcAnimation = new QPropertyAnimation(lrcPage,"geometry",this);
    lrcAnimation->setDuration(500);
    lrcAnimation->setStartValue(QRect(10,10+lrcPage->height(),lrcPage->width(),lrcPage->height()));
    lrcAnimation->setEndValue(QRect(10,10,lrcPage->width(),lrcPage->height()));
}

void Music::mousePressEvent(QMouseEvent *event)
{
    //按压的时候记录当前位置和窗口左上角的位置
    if(event->button() == Qt::LeftButton)
    {
        dragPosition = event->globalPos() - frameGeometry().topLeft();
        return;
    }
    //这里如果没有按压左键的话肯定是需要检测其他的按钮事件
    QWidget::mousePressEvent(event);
}

void Music::mouseMoveEvent(QMouseEvent *event)
{
    //只有当鼠标左键点击的时候才检测是否为移动，根据前面记录的偏移量来确定新的界面左上角的位置
    if(event->buttons() == Qt::LeftButton)
    {
        move(event->globalPos() - dragPosition);
        return;
    }
    QWidget::mouseMoveEvent(event);
}

void Music::onBtFormClick(int id)
{
    //1.获取到所有btForm中的控件
    QList<BtForm*> list = this->findChildren<BtForm*>();
    //2.把所有的控件除了和自己的id不同以外的都关闭
    foreach(BtForm* btForm , list)
    {
        if(id != btForm->getId())
        {
            btForm->clearBg();
        }
    }
    //3.设置当前栈空间显示当前界面
    ui->stackedWidget->setCurrentIndex(id-1);   //这里是从0开始的，所以下标需要减1
}

void Music::connectSignalAndSlot()
{
    //绑定每一个btForm的信号槽
    connect(ui->Rec,&BtForm::click,this,&Music::onBtFormClick);
    connect(ui->music,&BtForm::click,this,&Music::onBtFormClick);
    connect(ui->audio,&BtForm::click,this,&Music::onBtFormClick);
    connect(ui->like,&BtForm::click,this,&Music::onBtFormClick);
    connect(ui->local,&BtForm::click,this,&Music::onBtFormClick);
    connect(ui->recent,&BtForm::click,this,&Music::onBtFormClick);
    //处理我喜欢按钮点击
    connect(ui->likePage,&CommonPage::updateLikeMusic,this,&Music::onUpdateLikeMusic);
    connect(ui->localPage,&CommonPage::updateLikeMusic,this,&Music::onUpdateLikeMusic);
    connect(ui->recentPage,&CommonPage::updateLikeMusic,this,&Music::onUpdateLikeMusic);
    //绑定音乐播放点击，以及上下曲播放
    connect(ui->Play,&QPushButton::clicked,this,&Music::onPlayClicked);
    connect(ui->playUp,&QPushButton::clicked,this,&Music::onPlayUpCliked);
    connect(ui->playDown,&QPushButton::clicked,this,&Music::onPlayDownCliked);
    connect(ui->playMode,&QPushButton::clicked,this,&Music::onPlayBackModeCliked);
    //处理CommonPage中的全部播放的按钮
    connect(ui->localPage,&CommonPage::playAll,this,&Music::onPlayAll);
    connect(ui->likePage,&CommonPage::playAll,this,&Music::onPlayAll);
    connect(ui->recentPage,&CommonPage::playAll,this,&Music::onPlayAll);
    //处理CommonPage中的双击播放的功能
    connect(ui->localPage,&CommonPage::playMusicByIndex,this,&Music::playMusicByIndex);
    connect(ui->likePage,&CommonPage::playMusicByIndex,this,&Music::playMusicByIndex);
    connect(ui->recentPage,&CommonPage::playMusicByIndex,this,&Music::playMusicByIndex);
    //绑定声音设置
    connect(volumeTool,&VolumeTool::setSlience,this,&Music::setMusicSlience);
    connect(volumeTool,&VolumeTool::setMusicVolumn,this,&Music::setPlayerVolumn);
    //处理进度条的移动
    connect(ui->processBar,&MusicSlider::setMusicSliderPosition,this,&Music::onMusicSliderChanged);
    //处理lrc词界面显示
    connect(ui->lrcWord,&QPushButton::clicked,this,&Music::onLrcWordClicked);
}

QJsonArray Music::randomPicture()
{
    //通过组成随机的文字和图片的内容，然后进行返回对应需要的图片以及文字
    QVector<QString> randomVec;
    randomVec << "001.png";
    for(int i = 3;i<=40;++i)
    {
        randomVec << "0" + QString::number(i) + ".png";
    }
    std::random_shuffle(randomVec.begin(),randomVec.end());
    //将文字和图片组成一个数组并返回
    QJsonArray retArr;
    for(int i = 0;i<randomVec.size();++i)
    {
        QJsonObject obj;
        obj.insert("path",":/images/rec/"+randomVec[i]);
        QString strText = QString("推荐-%1").arg(i,3,10,QChar('0'));
        obj.insert("text",strText);
        retArr.append(obj);
    }
    return retArr;
}

void Music::onUpdateLikeMusic(bool isLike, const QString &musicId)
{
    //1.通过musicId设置喜欢
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsLike(isLike);
        //2.更新对应的musicList
        ui->likePage->reFresh(musicList);
        ui->localPage->reFresh(musicList);
        ui->recentPage->reFresh(musicList);
    }
}

void Music::initPlayer()
{
    //初始化播放器以及播放列表
    player = new QMediaPlayer(this);
    playList = new QMediaPlaylist(this);
    //添加播放循环方式 -- 默认按照列表循环播放
    playList->setPlaybackMode(QMediaPlaylist::Loop);
    //讲列表添加到对应的播放器中
    player->setPlaylist(playList);
    //设置默认音量大小
    player->setVolume(20);
    //这里的信息是由播放器产生的，不是界面中的物体
    connect(player,&QMediaPlayer::stateChanged,this,&Music::onPlayStateChanged);
    connect(playList,&QMediaPlaylist::playbackModeChanged,this,&Music::onPlayBackModeChanged);
    //绑定当音乐切换的时候，讲上一首音乐放到播放历史中
    connect(playList,&QMediaPlaylist::currentIndexChanged,this,&Music::onCurrentIndexChanged);
    //绑定歌曲总时间以及当前时间变化的时候，对控件的处理
    connect(player,&QMediaPlayer::durationChanged,this,&Music::onDurationChanged);
    connect(player,&QMediaPlayer::positionChanged,this,&Music::onPostionChanged);
    //处理歌曲变化的时候歌曲的信息在界面的同步
    connect(player,&QMediaPlayer::metaDataAvailableChanged,this,&Music::onMetaDataAvailableChanged);
}

void Music::onPlayClicked()
{
    qDebug() << "点击播放按钮";
    //如果不是播放状态，点击下一次就是播放状态；如果是播放状态下一次就是暂停状态
    if(player->state() == QMediaPlayer::PlayingState)
    {
        player->pause();
    }
    else if(player->state() == QMediaPlayer::PausedState)
    {
        player->play();
    }
    else if(player->state() == QMediaPlayer::StoppedState)
    {
        player->play();
    }
}

void Music::onPlayStateChanged()
{
    qDebug() << "播放状态改变";
    if(player->state() == QMediaPlayer::PlayingState)
    {
        ui->Play->setIcon(QIcon(":/images/play_on.png"));
    }
    else
    {
        ui->Play->setIcon(QIcon(":/images/play3.png"));
    }
}

void Music::onPlayUpCliked()
{
    playList->previous();
}

void Music::onPlayDownCliked()
{
    playList->next();
}

void Music::onPlayBackModeCliked()
{
    //获取当前的播放模式，然后按照循环 -- 随机 -- 单曲的顺序切换
    if(playList->playbackMode() == QMediaPlaylist::Loop)
    {
        ui->playMode->setToolTip("随机播放");
        playList->setPlaybackMode(QMediaPlaylist::Random);
    }
    else if(playList->playbackMode() == QMediaPlaylist::Random)
    {
        ui->playMode->setToolTip("单曲播放");
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    }
    else if(playList->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setToolTip("循环播放");
        playList->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else
    {
        qDebug() << "播放模式错误";
    }
}

void Music::onPlayBackModeChanged(QMediaPlaylist::PlaybackMode curMode)
{
    if(curMode == QMediaPlaylist::Loop)
    {
        ui->playMode->setIcon(QIcon(":/images/list_play.png"));
    }
    else if(curMode == QMediaPlaylist::Random)
    {
        ui->playMode->setIcon(QIcon(":/images/shuffle_2.png"));
    }
    else if(curMode == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setIcon(QIcon(":/images/single_play.png"));
    }
    else
    {
        qDebug() << "暂不支持该模式播放";
    }
}

void Music::onPlayAll(PageType pageType)
{
    //根据不同的页面的类型，拿到对应的数据
    CommonPage* page = nullptr;
    switch (pageType)
    {
    case PageType::LIKE_PAGE:
        page = ui->likePage;
        break;
    case PageType::LOCAL_PAGE:
        page = ui->localPage;
        break;
    case PageType::HISTORY_PAGE:
        page = ui->recentPage;
        break;
    default:
        qDebug() << "扩展";
        break;
    }
    //需要更新对应的list，然后开始播放
    playAllOfCommonPage(page,0);
}

void Music::playAllOfCommonPage(CommonPage *page, int index)
{
    //这里如果要播放其他页面的音乐或者是双击播放其他界面的音乐都是需要经过这个函数，这里需要设置当前的页面来处理最近播放
    curPage = page;
    //1.清理list
    playList->clear();
    //2.把对应的page中的音乐添加到list中
    page->addMusicToPlayer(musicList,playList);
    //3.设置起始索引
    playList->setCurrentIndex(index);
    //4.开始播放
    player->play();
}

void Music::playMusicByIndex(CommonPage *page, int index)
{
    playAllOfCommonPage(page,index);
}

void Music::onCurrentIndexChanged(int index)
{
    curIndex = index;
    //添加最近播放，这里通过拿到当前的page的index的音乐放入到最近播放列表即可
    const QString& musicId = curPage->getMusicIdByIndex(index);
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsHistory(true);
    }
    ui->recentPage->reFresh(musicList);
}

void Music::setMusicSlience(bool isMuted)
{
    player->setMuted(isMuted);
}

void Music::setPlayerVolumn(int volume)
{
    player->setVolume(volume);
}

void Music::onDurationChanged(qint64 duration)
{
    totalTime = duration;       //当音乐发生改变的时候，记录对应的总的播放时间
    //给界面显示总时间的控件设置时间
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60,2,10,QChar('0'))
                           .arg(duration/1000%60,2,10,QChar('0')));
}

void Music::onPostionChanged(qint64 duration)
{
    //设置时间进度
    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60,2,10,QChar('0'))
                             .arg(duration/1000%60,2,10,QChar('0')));
    //设置进度条进度
    ui->processBar->setStep((float)duration/(float)totalTime);
    //同步lrc歌词
    if(playList->currentIndex() >= 0)
    {
        lrcPage->showLrcWord(duration);
    }
}

void Music::onMusicSliderChanged(float value)
{
    //1.计算时长
    qint64 duration = totalTime * value;
    //2.更新当前的播放的时间
    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10, QChar('0'))
                             .arg(duration/1000%60, 2, 10, QChar('0')));
    //3.更新音乐到播放的地方
    player->setPosition(duration);
}

void Music::onMetaDataAvailableChanged(bool available)
{
    (void)available;
    qDebug() << "切换音乐";
    //1.通过音乐元数据获取到对应的信息
    QString singer = player->metaData("Author").toStringList().join(",");
    QString musicName = player->metaData("Title").toString();
    auto it = musicList.findMusicById(curPage->getMusicIdByIndex(curIndex));
    if(musicName.isEmpty())
    {
        //可以从当前页面的列表中找
        if(it != musicList.end())
        {
            singer = it->getSingerName();
            musicName = it->getMusicName();
        }
    }
    //2.将对应的信息填写到界面中
    ui->musicName->setText(musicName);
    ui->musicSinger->setText(singer);
    //获取图片数据
    QVariant coverImg = player->metaData("ThumbnailImage");
    if(coverImg.isValid())
    {
        QImage image = coverImg.value<QImage>();
        ui->musicCover->setPixmap(QPixmap::fromImage(image));
        ui->musicCover->setScaledContents(true);        //填充当前的空格
        //给commonpage中的图片信息进行设置
        curPage->setImageLabel(QPixmap::fromImage(image));
    }
    else
    {
        qDebug() << "没有歌曲的图片，设置默认";
    }
    //当歌曲切换的时候，获取全部的歌词
    if(it != musicList.end())
    {
        lrcPage->praseLrc(it->getLrcFilePath());
        //通过MusicInfo中的信息，设置歌曲以及作者
        lrcPage->showLrcTopInfo(singer,musicName);
    }
}

void Music::onLrcWordClicked()
{
    lrcPage->show();
    lrcAnimation->start();
}

void Music::on_volume_clicked()
{
    //展示音量
    //1.获取当前按钮图标所在的位置
    QPoint point = ui->volume->mapToGlobal(QPoint(0,0));    //获取相对屏幕左上角位置的坐标
    //2.获取到volume控件的左上角的位置
    QPoint leftTopPoint = point - QPoint(volumeTool->width()/2,volumeTool->height());
    //进行位置的细微调整
    leftTopPoint.setY(leftTopPoint.y()+30);
    leftTopPoint.setX(leftTopPoint.x()+15);
    //3.移动窗口的位置
    volumeTool->move(leftTopPoint);
    //4.展示窗口
    volumeTool->show();
}

void Music::on_addLocal_clicked()
{
    //1.创建一个文件对话框
    QFileDialog fileDialog(this);
    fileDialog.setWindowTitle("添加本地音乐");
    //2.文件对话框的打开格式
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    //3.设置对话框模式
    fileDialog.setFileMode(QFileDialog::ExistingFiles);     //可以的打开一个或多个文件
    //4.设置对话框MIME过滤器
    QStringList mimeList;
    mimeList << "application/octet-stream";
    fileDialog.setMimeTypeFilters(mimeList);
    //5.设置对话框默认打开路径
    QDir dir(QDir::currentPath());      //获取到这个项目的路径
    dir.cdUp();     //进入这个路径
    QString musicPath = dir.path() + "/QQMusic/musics/";    //获取到音乐的资源路径
    fileDialog.setDirectory(musicPath);
    //6.显示对话框并接收返回值
    //模态对话框，exec中是死循环
    if(fileDialog.exec() == QFileDialog::Accepted)
    {
        //添加本地音乐是在本地音乐中展示出来的
        ui->stackedWidget->setCurrentIndex(4);
        //获取对话框的返回值
        QList<QUrl> urls = fileDialog.selectedUrls();
        //拿到歌曲文件之后，将文件交给musicList进行管理
        musicList.addMusicByUrl(urls);
        //更新到本地音乐列表
        ui->localPage->reFresh(musicList);
    }
}

void Music::on_quit_clicked()
{
    QApplication::quit();       //退出并终止程序
}

void Music::on_min_clicked()
{
    //窗口最小化
    showMinimized();
}

void Music::on_max_clicked()
{
    //这里因为有些坐标是计算死的，所以暂时不支持
    QMessageBox::information(this,"温馨提示","暂时不支持该功能");
}
